home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / gg / tcpbug.lha / tcpbug / tcpbug.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-13  |  8.4 KB  |  422 lines

  1. /*
  2.  *  tcpbug.c  --  Accept a TCP/IP connection, and relay it to somewhere
  3.  *          else, while spying on the connection
  4.  *
  5.  *
  6.  *  This program is in the public domain.  You may do anything
  7.  *  you like with it.
  8.  *
  9.  *
  10.  *  Author:    Thomas Bellman
  11.  *        Lysator Computer Club
  12.  *        Linköping University
  13.  *        Sweden
  14.  *  email:    Bellman@Lysator.LiU.SE
  15.  *
  16.  *
  17.  *  Any opinions expressed in this code are the author's PERSONAL opinions,
  18.  *  and does NOT, repeat NOT, represent any official standpoint of Lysator,
  19.  *  even if so stated.
  20.  */
  21.  
  22.  
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdarg.h>
  27. #include <errno.h>
  28. #include <ctype.h>
  29. #include <signal.h>
  30. #include <locale.h>
  31. #include <limits.h>
  32.  
  33. #include <unistd.h>
  34. #include <sys/time.h>
  35. #include <sys/types.h>
  36. #include <netinet/in.h>
  37. #include <sys/socket.h>
  38. #include <arpa/inet.h>
  39. #include <netdb.h>
  40.  
  41. #include "ip/ip_misc.h"
  42. #include "relay.h"
  43.  
  44.  
  45. extern    int    getopt(int, char *const*, const char *);
  46. extern    int    optind;
  47. extern    char    *optarg;
  48.  
  49.  
  50.  
  51.  
  52. char        * progname        = "tcpbug";
  53. int          quiet_mode        = 0;
  54.  
  55. int          linewidth        = -1;
  56. /* Non-zero if a bytecount should be logged */
  57. int          bug_bytecount        = 0;
  58. /* Non-zero if logged data should be timestamped */
  59. int          bug_timestamp        = 0;
  60. /* Non-zero if logged data should be timestamped relative to the
  61.    establishing of the connection */
  62. int          bug_relative_timestamp= 0;
  63.  
  64.  
  65. struct bugstat {
  66.     /* The prefix character */
  67.     char          prefix;
  68.     /* Where to send bugged data */
  69.     FILE        * logfile;
  70.     /* Bytes passed this way */
  71.     unsigned long      nbytes;
  72.     /* Function to do actual printing of bugged data */
  73.     int         (*bugfun)(struct relay *, char *, size_t);
  74.     /* Time when bugger() was called */
  75.     struct timeval      time;
  76.     /* Time when the connection was established */
  77.     struct timeval      conntime;
  78. };
  79.  
  80.  
  81.  
  82. void
  83. log(const char *fmt, ...)
  84. {
  85.     va_list args;
  86.     va_start(args, fmt);
  87.     if (!quiet_mode)
  88.     vfprintf(stderr, fmt, args);
  89.     va_end(args);
  90. }
  91.  
  92.  
  93. void
  94. fatal(char    * msg)
  95. {
  96.     fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
  97.     exit(1);
  98. }
  99.  
  100.  
  101.  
  102. #define COLON()    (things_printed++ ? putc(':', bs->logfile),++*pos : 0)
  103.  
  104. int
  105. prefix(struct relay    * rel,
  106.        int          eof,
  107.        int        * pos)
  108. {
  109.     struct bugstat    * bs            = rel->userdata;
  110.     int              things_printed    = 0;
  111.  
  112.     if (bug_bytecount) {
  113.     char buf[sizeof bs->nbytes * CHAR_BIT];
  114.     COLON();
  115.     sprintf(buf, "%04lx", bs->nbytes);
  116.     fputs(buf, bs->logfile);
  117.     *pos += strlen(buf);
  118.     }
  119.     if (bug_timestamp) {
  120.     char buf[64];
  121.     COLON();
  122.     sprintf(buf, "%ld.%06ld", bs->time.tv_sec, bs->time.tv_usec);
  123.     fputs(buf, bs->logfile);
  124.     *pos += strlen(buf);
  125.     }
  126.     if (bug_relative_timestamp) {
  127.     char buf[64];
  128.     struct timeval diff;
  129.     COLON();
  130.     diff.tv_sec = bs->time.tv_sec - bs->conntime.tv_sec;
  131.     diff.tv_usec = bs->time.tv_usec - bs->conntime.tv_usec;
  132.     if (diff.tv_usec < 0)
  133.         diff.tv_usec += 1000000, diff.tv_sec -= 1;
  134.     sprintf(buf, "%ld.%06ld", diff.tv_sec, diff.tv_usec);
  135.     fputs(buf, bs->logfile);
  136.     *pos += strlen(buf);
  137.     }
  138.     putc(bs->prefix, bs->logfile);
  139.     if (eof)
  140.     fputs("EOF\n", bs->logfile);
  141.     else
  142.     putc(' ', bs->logfile);
  143.  
  144.     return 0;
  145. }
  146.  
  147.  
  148.  
  149. int
  150. bugger(struct relay    * rel,
  151.        char        * data,
  152.        size_t          datalen)
  153. {
  154.     struct bugstat    * bs        = rel->userdata;
  155.     int              pos        = 0;
  156.  
  157.     gettimeofday(&bs->time, NULL);
  158.     if (datalen == 0) {
  159.     prefix(rel, -1, &pos);
  160.     return 0;
  161.     }
  162.  
  163.     bs->bugfun(rel, data, datalen);
  164.     fflush(bs->logfile);
  165.  
  166.     return 0;
  167. }
  168.  
  169.  
  170.  
  171. int
  172. charbugger(struct relay    * rel,
  173.        char        * data,
  174.        size_t      datalen)
  175. {
  176.     int pos = 0;
  177.     struct bugstat *bs = rel->userdata;
  178.  
  179.     for ( ;  datalen > 0 ;  datalen--, data++, bs->nbytes++)
  180.     {
  181.     register int c = (unsigned char)*data;
  182.  
  183.     if (pos == 0)
  184.         prefix(rel, 0, &pos);
  185.  
  186.     if (isprint(c)) {
  187.         putc(' ', bs->logfile);
  188.         putc(' ', bs->logfile);
  189.         putc(c, bs->logfile);
  190.     } else if (c == '\n') {
  191.         putc(' ', bs->logfile);
  192.         putc('\\', bs->logfile);
  193.         putc('n', bs->logfile);
  194.     } else if (c == '\r') {
  195.         putc(' ', bs->logfile);
  196.         putc('\\', bs->logfile);
  197.         putc('r', bs->logfile);
  198.     } else if (c == '\b') {
  199.         putc(' ', bs->logfile);
  200.         putc('\\', bs->logfile);
  201.         putc('b', bs->logfile);
  202.     } else if (c == '\f') {
  203.         putc(' ', bs->logfile);
  204.         putc('\\', bs->logfile);
  205.         putc('f', bs->logfile);
  206.     } else if (c == '\t') {
  207.         putc(' ', bs->logfile);
  208.         putc('\\', bs->logfile);
  209.         putc('t', bs->logfile);
  210.     } else {
  211.         putc('0' + (c>>6 & 7), bs->logfile);
  212.         putc('0' + (c>>3 & 7), bs->logfile);
  213.         putc('0' + (c>>0 & 7), bs->logfile);
  214.     }
  215.     putc(' ', bs->logfile);
  216.     pos += 4;
  217.  
  218.     if (linewidth > 0  &&  pos >= linewidth) {
  219.         putc('\n', bs->logfile);
  220.         pos = 0;
  221.     }
  222.     }
  223.     if (pos != 0)
  224.     putc('\n', bs->logfile);
  225.  
  226.     return 0;
  227. }
  228.  
  229.  
  230.  
  231. int
  232. hexbugger(struct relay    * rel,
  233.       char        * data,
  234.       size_t      datalen)
  235. {
  236.     int pos = 0;
  237.     struct bugstat *bs = rel->userdata;
  238.     static char *hexdigits = "0123456789abcdef";
  239.  
  240.     for ( ;  datalen > 0 ;  datalen--, data++, bs->nbytes++)
  241.     {
  242.     register int c = (unsigned char)*data;
  243.  
  244.     if (pos == 0)
  245.         prefix(rel, 0, &pos);
  246.  
  247.     putc(hexdigits[c>>4 & 0xf], bs->logfile);
  248.     putc(hexdigits[c>>0 & 0xf], bs->logfile);
  249.     putc(' ', bs->logfile);
  250.     pos += 3;
  251.  
  252.     if (linewidth > 0  &&  pos >= linewidth) {
  253.         putc('\n', bs->logfile);
  254.         pos = 0;
  255.     }
  256.     }
  257.     if (pos != 0)
  258.     putc('\n', bs->logfile);
  259.  
  260.     return 0;
  261. }
  262.  
  263.  
  264.  
  265. int
  266. linebugger(struct relay    * rel,
  267.        char        * data,
  268.        size_t      datalen)
  269. {
  270.     int pos = 0;
  271.     struct bugstat *bs = rel->userdata;
  272.  
  273.     for ( ;  datalen > 0 ;  datalen--, data++, bs->nbytes++)
  274.     {
  275.     register int c = (unsigned char)*data;
  276.  
  277.     if (pos == 0)
  278.         prefix(rel, 0, &pos);
  279.  
  280.     putc(c, bs->logfile); pos++;
  281.     if (c == '\n') {
  282.         pos = 0;
  283.     }
  284. #if 0
  285.     if (linewidth > 0  &&  pos >= linewidth) {
  286.         putc('\n', bs->logfile);
  287.         pos = 0;
  288.     }
  289. #endif
  290.     }
  291.     if (pos != 0)
  292.     putc('\n', bs->logfile);
  293.  
  294.     return 0;
  295. }
  296.  
  297.  
  298.  
  299. void
  300. usage ()
  301. {
  302.     fprintf(stderr,
  303.         "usage: %s [-cx] [-btT] [-w linewidth] my-port  server-host  server-port\n",
  304.         progname);
  305.     fprintf(stderr,
  306.         "\t%s is a program that bugs a TCP/IP connection.  It waits\n"
  307.         "\tfor connections on a port that you specify, and then connects\n"
  308.         "\tto a server on a machine and a port you specify.  It then\n"
  309.         "\tprints out everything that is sent on the connection to\n"
  310.         "\tstdout.\n", progname
  311.     );
  312.     exit(1);
  313. }
  314.  
  315.  
  316. int
  317. main (argc, argv)
  318.       int argc;
  319.       char **argv;
  320. {
  321.     struct sockaddr_in      cliaddr;
  322.     int              cliaddrlen    = sizeof cliaddr;
  323.     int              listen_fd;
  324.     int              client_fd;
  325.     int              server_fd;
  326.     int              option;
  327.     int (*bugfun)(struct relay *, char *, size_t) = NULL;
  328.  
  329.     progname = argv[0];
  330.  
  331.     setlocale(LC_CTYPE, "");
  332.  
  333.     while ((option = getopt (argc, argv, "cxw:tTb")) != EOF)
  334.     {
  335.     switch ((char)option)
  336.     {
  337.     case 'c':
  338.         if (bugfun != NULL)
  339.         usage();
  340.         bugfun = charbugger;
  341.         if (linewidth < 0)
  342.         linewidth = 72;
  343.         break;
  344.     case 'x':
  345.         if (bugfun != NULL)
  346.         usage();
  347.         bugfun = hexbugger;
  348.         if (linewidth < 0)
  349.         linewidth = 72;
  350.         break;
  351.     case 'w':
  352.         linewidth = atoi(optarg);
  353.         break;
  354.     case 't':
  355.         bug_timestamp = 1;
  356.         break;
  357.     case 'T':
  358.         bug_relative_timestamp = 1;
  359.         break;
  360.     case 'b':
  361.         bug_bytecount = 1;
  362.         break;
  363.     default:
  364.         usage();
  365.         /* NOTREACHED */
  366.     }
  367.     }
  368.     if (argc - optind != 3)
  369.     usage();
  370.  
  371.     if (bugfun == NULL)
  372.     bugfun = linebugger;
  373.  
  374.     listen_fd = tcp_listen(NULL, argv[optind]);
  375.     if (listen_fd < 0)
  376.     fatal("can't listen to port");
  377.     client_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &cliaddrlen);
  378.     if (client_fd < 0)
  379.     fatal("accept failed");
  380.     log("[Connection from %s port %d]\n",
  381.     inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
  382.     close(listen_fd);
  383.     server_fd = tcp_open(argv[optind+1], argv[optind+2], NULL, NULL);
  384.     if (server_fd < 0)
  385.     fatal("can't connect to server");
  386.     
  387.     {
  388.     struct relay      fds[2];
  389.     struct bugstat      buggers[2];
  390.     struct timeval      now;
  391.  
  392.     gettimeofday(&now, NULL);
  393.     signal(SIGPIPE, SIG_IGN);
  394.  
  395.     fds[0].source = client_fd;
  396.     fds[0].dest = server_fd;
  397.     fds[0].readerror = 0;
  398.     fds[0].writeerror = 0;
  399.     fds[0].userdata = &buggers[0];
  400.     buggers[0].nbytes = 0;
  401.     buggers[0].prefix = '>';
  402.     buggers[0].logfile = stdout;
  403.     buggers[0].bugfun = bugfun;
  404.     buggers[0].conntime = now;
  405.  
  406.     fds[1].source = server_fd;
  407.     fds[1].dest = client_fd;
  408.     fds[1].readerror = 0;
  409.     fds[1].writeerror = 0;
  410.     fds[1].userdata = &buggers[1];
  411.     buggers[1].nbytes = 0;
  412.     buggers[1].prefix = '<';
  413.     buggers[1].logfile = stdout;
  414.     buggers[1].bugfun = bugfun;
  415.     buggers[1].conntime = now;
  416.  
  417.     relay_all(fds, 2, bugger);
  418.     }
  419.  
  420.     return 0;
  421. }
  422.